package com.fh.huanxin.controller;

import java.net.URL;

import org.apache.commons.lang3.StringUtils;

import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fh.huanxin.HTTPClientUtils;
import com.fh.huanxin.com.Constants;
import com.fh.huanxin.com.HTTPMethod;
import com.fh.huanxin.com.Roles;
import com.fh.huanxin.vo.ClientSecretCredential;
import com.fh.huanxin.vo.Credential;
import com.fh.huanxin.vo.EndPoints;
import com.fh.util.Logger;
import com.fh.util.PageData;

/**
 * 
 * @包名 :com.fh.huanxin.controller
 * @文件名 :HxmsgDasis.java
 *      TODO 类作用：环信基础管理
 * @Author: 孙超文 386480250@qq.com
 * @Date: 2015-7-7 下午5:58:36
 */
public class HxmsgDasis {
	protected static Logger logger = Logger.getLogger(HxmsgDasis.class);
	private static final JsonNodeFactory factory = new JsonNodeFactory(false);

	// 通过app的client_id和client_secret来获取app管理员token
	private static Credential credential = new ClientSecretCredential(Constants.APP_CLIENT_ID,
			Constants.APP_CLIENT_SECRET, Roles.USER_ROLE_APPADMIN);

	public static void main(String[] args) {
		PageData pd = new PageData();
		pd.put("hxusername", "scw_vip");
		pd.put("nickname", "scw_vip");
		pd.put("hxpassword", "1");
		HxmsgDasis.hxnickname(pd);
	}

	/**
	 * 
	 * TODO 方法作用：单个环信用户注册
	 * 
	 * @param pd
	 * @return
	 * @Author: 孙超文
	 * @Date: 2015-7-7 下午12:37:06
	 */
	public static Object hxuserreg(PageData pd) {
		ObjectNode datanode = JsonNodeFactory.instance.objectNode();
		datanode.put("username", pd.getString("hxusername"));
		datanode.put("password", pd.getString("hxpassword"));
		ObjectNode createNewIMUserSingleNode = createNewIMUserSingle(datanode);
		if (null != createNewIMUserSingleNode) {
			logger.info("注册IM用户[单个]: " + createNewIMUserSingleNode.toString());
		}
		System.out.println("注册IM用户[单个]:" + createNewIMUserSingleNode);
		return createNewIMUserSingleNode;
	}

	/**
	 * 
	 * TODO 方法作用：环信用户登陆
	 * 
	 * @param pd
	 * @return
	 * @Author: 孙超文
	 * @Date: 2015-7-7 下午12:37:06
	 */
	public static Object hxuserlog(PageData pd) {
		ObjectNode datanode = JsonNodeFactory.instance.objectNode();
		datanode.put("username", pd.getString("hxusername"));
		datanode.put("password", pd.getString("hxpassword"));
		ObjectNode imUserLoginNode = imUserLogin(datanode.get("username").asText(), datanode.get("password").asText());
		if (null != imUserLoginNode) {
			logger.info("IM用户登录: " + imUserLoginNode.toString());
		}
		System.out.println("环信用户登陆" + imUserLoginNode);
		return imUserLoginNode;
	}

	/**
	 * 
	 * TODO 方法作用：修改环信昵称
	 * 
	 * @param pd
	 * @return
	 * @Author: 孙超文
	 * @Date: 2015-7-7 下午4:53:12
	 */
	public static Object hxnickname(PageData pd) {
		ObjectNode datanode = JsonNodeFactory.instance.objectNode();
		datanode.put("username", pd.getString("hxusername"));
		datanode.put("nickname", pd.getString("nickname"));
		ObjectNode imUserLoginNode = updateNicakname(datanode.get("username").asText(), datanode.get("nickname")
				.asText());
		if (null != imUserLoginNode) {
			logger.info("IM用户登录: " + imUserLoginNode.toString());
		}
		System.out.println("环信用户登陆" + imUserLoginNode);
		return imUserLoginNode;
	}

	/**
	 * 
	 * TODO 方法作用：删除环信用户
	 * 
	 * @param pd
	 * @return
	 * @Author: 孙超文
	 * @Date: 2015-7-7 下午12:37:06
	 */
	public static Object hxuserdele(PageData pd) {
		String userName = pd.getString("hxusername");
		ObjectNode deleteIMUserByuserNameNode = deleteIMUserByuserName(userName);
		if (null != deleteIMUserByuserNameNode) {
			logger.info("删除IM用户[单个]: " + deleteIMUserByuserNameNode.toString());
		}
		System.out.println("删除环信用户" + deleteIMUserByuserNameNode);
		return deleteIMUserByuserNameNode;
	}

	/**
	 * 
	 * TODO 方法作用：检查好友在线
	 * 
	 * @param pd
	 * @return 键值对 值为 online(在线) 或者 offline（离线）
	 * @Author: 孙超文
	 * @Date: 2015-7-7 下午12:59:04
	 */
	public static Object hxuserstatus(PageData pd) {
		String targetUserName = pd.getString("hxusername");
		ObjectNode usernode = getUserStatus(targetUserName);
		if (null != usernode) {
			logger.info("检测用户是否在线: " + usernode.toString());
		}
		return usernode;
	}

	/**
	 * 
	 * TODO 方法作用：检查用户离线消息数
	 * 
	 * @param pd
	 * @return 键值对 值为 online(在线) 或者 offline（离线）
	 * @Author: 孙超文
	 * @Date: 2015-7-7 下午12:59:04
	 */
	public static Object hxuseroffmsgcount(PageData pd) {
		// 检测用户是否在线
		String targetUserName = pd.getString("hxusername");
		ObjectNode usernode = getUserofflinemsgCount(targetUserName);
		if (null != usernode) {
			logger.info("检测用户离线消息: " + usernode.toString());
		}
		return usernode;
	}

	/**
	 * 注册IM用户[单个]
	 * 
	 * 给指定Constants.APPKEY创建一个新的用户
	 * 
	 * @param dataNode
	 * @return
	 */
	public static ObjectNode createNewIMUserSingle(ObjectNode dataNode) {

		ObjectNode objectNode = factory.objectNode();

		// check Constants.APPKEY format
		if (!HTTPClientUtils.match("^(?!-)[0-9a-zA-Z\\-]+#[0-9a-zA-Z]+", Constants.APPKEY)) {
			logger.error("Bad format of Constants.APPKEY: " + Constants.APPKEY);

			objectNode.put("message", "Bad format of Constants.APPKEY");

			return objectNode;
		}

		objectNode.removeAll();

		// check properties that must be provided
		if ((null != dataNode) && !dataNode.has("username")) {
			logger.error("Property that named username must be provided .");

			objectNode.put("message", "Property that named username must be provided .");

			return objectNode;
		}
		if ((null != dataNode) && !dataNode.has("password")) {
			logger.error("Property that named password must be provided .");

			objectNode.put("message", "Property that named password must be provided .");

			return objectNode;
		}

		try {

			objectNode = HTTPClientUtils.sendHTTPRequest(EndPoints.USERS_URL, credential, dataNode,
					HTTPMethod.METHOD_POST);

		} catch (Exception e) {
			e.printStackTrace();
		}

		return objectNode;
	}

	/**
	 * IM用户登录
	 * 
	 * @param username
	 * @param password
	 * @return
	 */
	public static ObjectNode imUserLogin(String username, String password) {

		ObjectNode objectNode = factory.objectNode();

		// check appKey format
		if (!HTTPClientUtils.match("^(?!-)[0-9a-zA-Z\\-]+#[0-9a-zA-Z]+", Constants.APPKEY)) {
			logger.error("Bad format of Appkey: " + Constants.APPKEY);

			objectNode.put("message", "Bad format of Appkey");

			return objectNode;
		}
		if (StringUtils.isEmpty(username)) {
			logger.error("Your username must be provided，the value is username of imuser.");

			objectNode.put("message", "Your username must be provided，the value is username of imuser.");

			return objectNode;
		}
		if (StringUtils.isEmpty(password)) {
			logger.error("Your password must be provided，the value is username of imuser.");

			objectNode.put("message", "Your password must be provided，the value is username of imuser.");

			return objectNode;
		}

		try {
			ObjectNode dataNode = factory.objectNode();
			dataNode.put("grant_type", "password");
			dataNode.put("username", username);
			dataNode.put("password", password);

			objectNode = HTTPClientUtils.sendHTTPRequest(EndPoints.TOKEN_APP_URL, null, dataNode,
					HTTPMethod.METHOD_POST);

		} catch (Exception e) {
			throw new RuntimeException("Some errors occurred while fetching a token by username and password .");
		}

		return objectNode;
	}

	/**
	 * 删除IM用户
	 * 
	 * @param username
	 * @param password
	 * @return
	 */
	public static ObjectNode deleteIMUserByuserName(String userName) {
		ObjectNode objectNode = factory.objectNode();

		// check Constants.APPKEY format
		if (!HTTPClientUtils.match("^(?!-)[0-9a-zA-Z\\-]+#[0-9a-zA-Z]+", Constants.APPKEY)) {
			logger.error("Bad format of Constants.APPKEY: " + Constants.APPKEY);

			objectNode.put("message", "Bad format of Constants.APPKEY");

			return objectNode;
		}

		try {

			URL deleteUserPrimaryUrl = HTTPClientUtils
					.getURL(Constants.APPKEY.replace("#", "/") + "/users/" + userName);
			objectNode = HTTPClientUtils.sendHTTPRequest(deleteUserPrimaryUrl, credential, null,
					HTTPMethod.METHOD_DELETE);

		} catch (Exception e) {
			e.printStackTrace();
		}

		return objectNode;
	}

	/**
	 * 修改用户昵称
	 * 
	 * @param username
	 * @param password
	 * @return
	 */
	public static ObjectNode updateNicakname(String userName, String nickname) {
		ObjectNode objectNode = factory.objectNode();

		// check Constants.APPKEY format
		if (!HTTPClientUtils.match("^(?!-)[0-9a-zA-Z\\-]+#[0-9a-zA-Z]+", Constants.APPKEY)) {
			logger.error("Bad format of Constants.APPKEY: " + Constants.APPKEY);

			objectNode.put("message", "Bad format of Constants.APPKEY");

			return objectNode;
		}

		if (StringUtils.isEmpty(userName)) {
			logger.error("Property that named userName must be provided，the value is username of imuser.");

			objectNode.put("message", "Property that named userName must be provided，the value is username or imuser.");

			return objectNode;
		}

		if (StringUtils.isEmpty(nickname)) {
			logger.error("Property that named newpassword must be provided .");

			objectNode.put("message", "Property that named newpassword must be provided .");

			return objectNode;
		}

		try {
			URL modifyIMUserPasswordWithAdminTokenUrl = HTTPClientUtils.getURL(Constants.APPKEY.replace("#", "/")
					+ "/users/" + userName);
			ObjectNode datanode = JsonNodeFactory.instance.objectNode();
			datanode.put("nickname", nickname);
			objectNode = HTTPClientUtils.sendHTTPRequest(modifyIMUserPasswordWithAdminTokenUrl, credential, datanode,
					HTTPMethod.METHOD_PUT);

		} catch (Exception e) {
			e.printStackTrace();
		}

		return objectNode;
	}

	/**
	 * 检测用户是否在线
	 * 
	 * @param username
	 * 
	 * @return
	 */
	public static ObjectNode getUserStatus(String username) {
		ObjectNode objectNode = factory.objectNode();

		// check appKey format
		if (!HTTPClientUtils.match("^(?!-)[0-9a-zA-Z\\-]+#[0-9a-zA-Z]+", Constants.APPKEY)) {
			logger.error("Bad format of Appkey: " + Constants.APPKEY);
			objectNode.put("message", "Bad format of Appkey");
			return objectNode;
		}

		// check properties that must be provided
		if (StringUtils.isEmpty(username)) {
			logger.error("You must provided a targetUserName .");
			objectNode.put("message", "You must provided a targetUserName .");
			return objectNode;
		}

		try {
			URL userStatusUrl = HTTPClientUtils.getURL(Constants.APPKEY.replace("#", "/") + "/users/" + username
					+ "/status");
			objectNode = HTTPClientUtils.sendHTTPRequest(userStatusUrl, credential, null, HTTPMethod.METHOD_GET);
			String userStatus = objectNode.get("data").path(username).asText();
			if ("online".equals(userStatus)) {
				logger.error(String.format("The status of user[%s] is : [%s] .", username, userStatus));
			} else if ("offline".equals(userStatus)) {
				logger.error(String.format("The status of user[%s] is : [%s] .", username, userStatus));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		return objectNode;
	}

	/**
	 * 
	 * TODO 方法作用：离线消息
	 * 
	 * @param username
	 * @return
	 * @Author: 孙超文
	 * @Date: 2015-7-7 下午5:06:40
	 */
	public static ObjectNode getUserofflinemsgCount(String username) {
		ObjectNode objectNode = factory.objectNode();

		// check appKey format
		if (!HTTPClientUtils.match("^(?!-)[0-9a-zA-Z\\-]+#[0-9a-zA-Z]+", Constants.APPKEY)) {
			logger.error("Bad format of Appkey: " + Constants.APPKEY);
			objectNode.put("message", "Bad format of Appkey");
			return objectNode;
		}

		// check properties that must be provided
		if (StringUtils.isEmpty(username)) {
			logger.error("You must provided a targetUserName .");
			objectNode.put("message", "You must provided a targetUserName .");
			return objectNode;
		}

		try {
			URL userStatusUrl = HTTPClientUtils.getURL(Constants.APPKEY.replace("#", "/") + "/users/" + username
					+ "/offline_msg_count");
			objectNode = HTTPClientUtils.sendHTTPRequest(userStatusUrl, credential, null, HTTPMethod.METHOD_GET);
			String userStatus = objectNode.get("data").path(username).asText();
			if ("online".equals(userStatus)) {
				logger.error(String.format("The status of user[%s] is : [%s] .", username, userStatus));
			} else if ("offline".equals(userStatus)) {
				logger.error(String.format("The status of user[%s] is : [%s] .", username, userStatus));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		return objectNode;
	}

}
